package icu.funkye.confine.spring.scanner;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import icu.funkye.confine.annotations.ConfineLimiter;
import icu.funkye.confine.limiter.RateLimiterFactory;
import icu.funkye.confine.spring.util.SpringProxyUtils;
import icu.funkye.confine.constants.ConfineConstant;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.util.StringUtils;

/**
 * @author jianbin.chen
 */
public class ConfineScanner extends DefaultAdvisorAutoProxyCreator {

    @Override
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        try {
            Class<?> serviceInterface = SpringProxyUtils.findTargetClass(bean);
            if (serviceInterface != null) {
                Method[] methods = serviceInterface.getDeclaredMethods();
                for (Method method : methods) {
                    ConfineLimiter confineAnnotation = method.getAnnotation(ConfineLimiter.class);
                    if (confineAnnotation != null) {
                        String methodName = confineAnnotation.method();
                        if (StringUtils.isEmpty(methodName)) {
                            StringBuilder sb = new StringBuilder(serviceInterface.getName());
                            sb.append(ConfineConstant.SPLIT).append(method.getName());
                            Parameter[] parameters = method.getParameters();
                            for (Parameter parameter : parameters) {
                                sb.append(ConfineConstant.SPLIT).append(parameter.getName());
                            }
                            methodName = sb.toString();
                        }
                        RateLimiterFactory.create(methodName, confineAnnotation.tps(), confineAnnotation.waitTime(),
                            confineAnnotation.rt(), confineAnnotation.limitType());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bean;
    }

}
